package emulator.shell.GUI.menu;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.Observable;
import java.util.Observer;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.JTextPane;
import javax.swing.table.TableColumn;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;

import emulator.hardware.io.peripherals.iec.IecSim;
import emulator.shell.GUI.IECwindow.DeviceTableModel;
import emulator.shell.GUI.windows.ManagedWindow;
import emulator.shell.GUI.windows.WindowManager;

public class WindowIEC implements ActionListener, Observer {

	private int window_id;
	private WindowManager window_manager;
	private JTextPane content = null;
	private IecSim iec_sim = null;
	private JCheckBox log_state_button = null;
	private JButton clear_log_button;
	
	public WindowIEC(WindowManager window_manager, int window_id, IecSim iec_sim)
	{
		this.window_manager = window_manager;
		this.window_id = window_id;
		this.iec_sim = iec_sim;
	}

	
	@Override
	public void actionPerformed(ActionEvent arg0) {
		if (window_manager.isWindowActive(window_id))
			closeWindow();
		else
			openWindow();
	}

	private void openWindow() {
		ManagedWindow window = window_manager.createWindow(window_id, "Debug IEC");
		addComponentsToPane(window.getContentPane());
		window.restorePosition();
		window.setVisible(true);
		fetchLogLines();
		iec_sim.addLogObserver(this);
	}

	private void closeWindow() {
		iec_sim.deleteLogObserver(this);
		window_manager.closeWindow(window_id);
	}

	private void addComponentsToPane(Container pane)
	{
        if (!(pane.getLayout() instanceof BorderLayout)) {
            pane.add(new JLabel("Container doesn't use BorderLayout!"));
            return;
        }

        JPanel device_panel = createDevicePanel();
		JPanel log_panel = createLogPanel();
	    JSplitPane splitPane = new JSplitPane(
	    			JSplitPane.VERTICAL_SPLIT,
                	device_panel, log_panel);
	    splitPane.setOneTouchExpandable(true);
	    splitPane.setDividerLocation(150);

//		Provide minimum sizes for the two components in the split pane
	    Dimension minimumSize = new Dimension(100, 50);
	    device_panel.setMinimumSize(minimumSize);
	    log_panel.setMinimumSize(minimumSize);

		pane.add(splitPane, BorderLayout.CENTER);
	}


	private JPanel createDevicePanel() {
		JPanel panel_config = new JPanel();
		panel_config.setLayout(new BorderLayout());

        JLabel label = new JLabel("Devices");
        panel_config.add(label, BorderLayout.PAGE_START);
		
        JTable table = new JTable();
        DeviceTableModel table_model = new DeviceTableModel();
		table.setModel(table_model);
        for (int i = 0; i < table_model.getColumnCount(); i++) {
        	TableColumn column = table.getColumnModel().getColumn(i);
            column.setPreferredWidth(table_model.getColumnWidth(i));
        }

        table.setFillsViewportHeight(true);
        panel_config.add(new JScrollPane(table), BorderLayout.CENTER);
        
		return panel_config;
	}

	private JPanel createLogPanel() {
		JPanel panel_log = new JPanel();
		panel_log.setLayout(new BorderLayout());
        
        JLabel label = new JLabel("Debug Log");
        panel_log.add(label, BorderLayout.PAGE_START);
        
	    content = new JTextPane();
	    content.setEditable( false );
	    content.setPreferredSize( new Dimension( 300, 300 ) );
	    panel_log.add(new JScrollPane(content), BorderLayout.CENTER);
	    
		log_state_button = new JCheckBox("Log state");
		log_state_button.addItemListener(new ToggleLogState());
		log_state_button.setSelected(iec_sim.isStateLogEnabled());
		clear_log_button = new JButton("Clear log");
		clear_log_button.addActionListener(new ClearLog());
		
		JPanel panel = new JPanel();
		panel.add(log_state_button, BorderLayout.WEST);
		panel.add(clear_log_button, BorderLayout.EAST);
		panel_log.add(panel, BorderLayout.PAGE_END);
		return panel_log;
	}

	private void fetchLogLines() {
		Document doc = content.getDocument();
		String log_line = iec_sim.getLogLine();
		while (log_line != null)
		{
		    try {
		    	doc.insertString(doc.getLength(), log_line, null);
		    } catch (BadLocationException e) {}
			log_line = iec_sim.getLogLine();
		}
	}
	
	@Override
	public void update(Observable arg0, Object arg1) {
        javax.swing.SwingUtilities.invokeLater(new LogWriteEvent());
	}

	public class LogWriteEvent implements Runnable {

		@Override
		public void run() {
			fetchLogLines();
		}
	}

	public class ClearLog implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent event) {
			Document doc = content.getDocument();
			try {
				doc.remove(0, doc.getLength());
			} catch (BadLocationException e) { }
		}
	}

	public class ToggleLogState implements ItemListener {

		@Override
		public void itemStateChanged(ItemEvent event) {
			iec_sim.setStateLogEnabled(log_state_button.isSelected());
		}
	}
}
